﻿using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace Basic.Identity4;

public class AuthorizationUtils
{
    public static string SecretKey { get; set; }

    private static SymmetricSecurityKey _symmetricKey;
    public static SymmetricSecurityKey SymmetricKey => _symmetricKey ??= new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecretKey));

    private static SigningCredentials _credentialsKey;
    public static SigningCredentials CredentialsKey => _credentialsKey ??= new SigningCredentials(SymmetricKey, SecurityAlgorithms.HmacSha256);

    /// <summary>
    /// 获取Token
    /// </summary>
    /// <param name="claims"></param>
    /// <param name="timeSpan"></param>
    /// <returns></returns>
    public static string GetToken(List<Claim> claims, TimeSpan timeSpan)
    {
        DateTime authTime = DateTime.Now;
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(claims),
            IssuedAt = authTime,
            Expires = authTime.Add(timeSpan), /* 到期时间 */
            SigningCredentials = CredentialsKey,
            CompressionAlgorithm = SecurityAlgorithms.HmacSha256,
            Issuer = "Issuer",
            Audience = "Audience",
        };
        JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
        JwtSecurityToken token = tokenHandler.CreateJwtSecurityToken(tokenDescriptor);
        return tokenHandler.WriteToken(token);
    }

    /// <summary>
    /// 验证Token是否有效
    /// </summary>
    /// <param name="token"></param>
    /// <param name="validTime">输出token剩余有效时间</param>
    /// <param name="claimsIdentity">输出身份信息</param>
    /// <returns></returns>
    public static bool VerifyToken(string tokenStr, out ClaimsPrincipal claimsPrincipal)
    {
        claimsPrincipal = null;
        JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
        if (tokenStr.StartsWith("Bearer "))
            tokenStr = tokenStr.Substring(7);

        if (tokenHandler.CanReadToken(tokenStr))
        {
            JwtSecurityToken tokenObj = tokenHandler.ReadJwtToken(tokenStr);
            TokenValidationParameters param = new TokenValidationParameters()
            {
                ValidateAudience = true,
                ValidAudiences = tokenObj.Audiences,
                ValidateIssuer = true,
                ValidIssuer = "Issuer",
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                RequireExpirationTime = true,
                IssuerSigningKey = AuthorizationUtils.SymmetricKey,//SymmetricKey,
            };
            // Token通过秘钥解析出来的SecurityToken
            try
            {
                claimsPrincipal = tokenHandler.ValidateToken(tokenStr, param, out SecurityToken sToken);
                if (sToken != null)
                {
                    TimeSpan validTime = sToken.ValidTo - DateTime.UtcNow;
                    return validTime.TotalSeconds > 0;
                }
            }
            catch (Exception ex) { }
        }
        return false;
    }
}
